1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gio.Subprocess; 26 27 private import gio.AsyncResultIF; 28 private import gio.Cancellable; 29 private import gio.InitableIF; 30 private import gio.InitableT; 31 private import gio.InputStream; 32 private import gio.OutputStream; 33 private import gio.c.functions; 34 public import gio.c.types; 35 private import glib.Bytes; 36 private import glib.ConstructionException; 37 private import glib.ErrorG; 38 private import glib.GException; 39 private import glib.Str; 40 private import glib.c.functions; 41 private import gobject.ObjectG; 42 43 44 /** 45 * #GSubprocess allows the creation of and interaction with child 46 * processes. 47 * 48 * Processes can be communicated with using standard GIO-style APIs (ie: 49 * #GInputStream, #GOutputStream). There are GIO-style APIs to wait for 50 * process termination (ie: cancellable and with an asynchronous 51 * variant). 52 * 53 * There is an API to force a process to terminate, as well as a 54 * race-free API for sending UNIX signals to a subprocess. 55 * 56 * One major advantage that GIO brings over the core GLib library is 57 * comprehensive API for asynchronous I/O, such 58 * g_output_stream_splice_async(). This makes GSubprocess 59 * significantly more powerful and flexible than equivalent APIs in 60 * some other languages such as the `subprocess.py` 61 * included with Python. For example, using #GSubprocess one could 62 * create two child processes, reading standard output from the first, 63 * processing it, and writing to the input stream of the second, all 64 * without blocking the main loop. 65 * 66 * A powerful g_subprocess_communicate() API is provided similar to the 67 * `communicate()` method of `subprocess.py`. This enables very easy 68 * interaction with a subprocess that has been opened with pipes. 69 * 70 * #GSubprocess defaults to tight control over the file descriptors open 71 * in the child process, avoiding dangling-fd issues that are caused by 72 * a simple fork()/exec(). The only open file descriptors in the 73 * spawned process are ones that were explicitly specified by the 74 * #GSubprocess API (unless %G_SUBPROCESS_FLAGS_INHERIT_FDS was 75 * specified). 76 * 77 * #GSubprocess will quickly reap all child processes as they exit, 78 * avoiding "zombie processes" remaining around for long periods of 79 * time. g_subprocess_wait() can be used to wait for this to happen, 80 * but it will happen even without the call being explicitly made. 81 * 82 * As a matter of principle, #GSubprocess has no API that accepts 83 * shell-style space-separated strings. It will, however, match the 84 * typical shell behaviour of searching the PATH for executables that do 85 * not contain a directory separator in their name. By default, the `PATH` 86 * of the current process is used. You can specify 87 * %G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP to use the `PATH` of the 88 * launcher environment instead. 89 * 90 * #GSubprocess attempts to have a very simple API for most uses (ie: 91 * spawning a subprocess with arguments and support for most typical 92 * kinds of input and output redirection). See g_subprocess_new(). The 93 * #GSubprocessLauncher API is provided for more complicated cases 94 * (advanced types of redirection, environment variable manipulation, 95 * change of working directory, child setup functions, etc). 96 * 97 * A typical use of #GSubprocess will involve calling 98 * g_subprocess_new(), followed by g_subprocess_wait_async() or 99 * g_subprocess_wait(). After the process exits, the status can be 100 * checked using functions such as g_subprocess_get_if_exited() (which 101 * are similar to the familiar WIFEXITED-style POSIX macros). 102 * 103 * Since: 2.40 104 */ 105 public class Subprocess : ObjectG, InitableIF 106 { 107 /** the main Gtk struct */ 108 protected GSubprocess* gSubprocess; 109 110 /** Get the main Gtk struct */ 111 public GSubprocess* getSubprocessStruct(bool transferOwnership = false) 112 { 113 if (transferOwnership) 114 ownedRef = false; 115 return gSubprocess; 116 } 117 118 /** the main Gtk struct as a void* */ 119 protected override void* getStruct() 120 { 121 return cast(void*)gSubprocess; 122 } 123 124 /** 125 * Sets our main struct and passes it to the parent class. 126 */ 127 public this (GSubprocess* gSubprocess, bool ownedRef = false) 128 { 129 this.gSubprocess = gSubprocess; 130 super(cast(GObject*)gSubprocess, ownedRef); 131 } 132 133 // add the Initable capabilities 134 mixin InitableT!(GSubprocess); 135 136 137 /** */ 138 public static GType getType() 139 { 140 return g_subprocess_get_type(); 141 } 142 143 /** 144 * Create a new process with the given flags and argument list. 145 * 146 * The argument list is expected to be %NULL-terminated. 147 * 148 * Params: 149 * argv = commandline arguments for the subprocess 150 * flags = flags that define the behaviour of the subprocess 151 * 152 * Returns: A newly created #GSubprocess, or %NULL on error (and @error 153 * will be set) 154 * 155 * Since: 2.40 156 * 157 * Throws: GException on failure. 158 * Throws: ConstructionException GTK+ fails to create the object. 159 */ 160 public this(string[] argv, GSubprocessFlags flags) 161 { 162 GError* err = null; 163 164 auto __p = g_subprocess_newv(Str.toStringzArray(argv), flags, &err); 165 166 if (err !is null) 167 { 168 throw new GException( new ErrorG(err) ); 169 } 170 171 if(__p is null) 172 { 173 throw new ConstructionException("null returned by newv"); 174 } 175 176 this(cast(GSubprocess*) __p, true); 177 } 178 179 /** 180 * Communicate with the subprocess until it terminates, and all input 181 * and output has been completed. 182 * 183 * If @stdin_buf is given, the subprocess must have been created with 184 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. The given data is fed to the 185 * stdin of the subprocess and the pipe is closed (ie: EOF). 186 * 187 * At the same time (as not to cause blocking when dealing with large 188 * amounts of data), if %G_SUBPROCESS_FLAGS_STDOUT_PIPE or 189 * %G_SUBPROCESS_FLAGS_STDERR_PIPE were used, reads from those 190 * streams. The data that was read is returned in @stdout and/or 191 * the @stderr. 192 * 193 * If the subprocess was created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 194 * @stdout_buf will contain the data read from stdout. Otherwise, for 195 * subprocesses not created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 196 * @stdout_buf will be set to %NULL. Similar provisions apply to 197 * @stderr_buf and %G_SUBPROCESS_FLAGS_STDERR_PIPE. 198 * 199 * As usual, any output variable may be given as %NULL to ignore it. 200 * 201 * If you desire the stdout and stderr data to be interleaved, create 202 * the subprocess with %G_SUBPROCESS_FLAGS_STDOUT_PIPE and 203 * %G_SUBPROCESS_FLAGS_STDERR_MERGE. The merged result will be returned 204 * in @stdout_buf and @stderr_buf will be set to %NULL. 205 * 206 * In case of any error (including cancellation), %FALSE will be 207 * returned with @error set. Some or all of the stdin data may have 208 * been written. Any stdout or stderr data that has been read will be 209 * discarded. None of the out variables (aside from @error) will have 210 * been set to anything in particular and should not be inspected. 211 * 212 * In the case that %TRUE is returned, the subprocess has exited and the 213 * exit status inspection APIs (eg: g_subprocess_get_if_exited(), 214 * g_subprocess_get_exit_status()) may be used. 215 * 216 * You should not attempt to use any of the subprocess pipes after 217 * starting this function, since they may be left in strange states, 218 * even if the operation was cancelled. You should especially not 219 * attempt to interact with the pipes while the operation is in progress 220 * (either from another thread or if using the asynchronous version). 221 * 222 * Params: 223 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 224 * cancellable = a #GCancellable 225 * stdoutBuf = data read from the subprocess stdout 226 * stderrBuf = data read from the subprocess stderr 227 * 228 * Returns: %TRUE if successful 229 * 230 * Since: 2.40 231 * 232 * Throws: GException on failure. 233 */ 234 public bool communicate(Bytes stdinBuf, Cancellable cancellable, out Bytes stdoutBuf, out Bytes stderrBuf) 235 { 236 GBytes* outstdoutBuf = null; 237 GBytes* outstderrBuf = null; 238 GError* err = null; 239 240 auto __p = g_subprocess_communicate(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 241 242 if (err !is null) 243 { 244 throw new GException( new ErrorG(err) ); 245 } 246 247 stdoutBuf = new Bytes(outstdoutBuf); 248 stderrBuf = new Bytes(outstderrBuf); 249 250 return __p; 251 } 252 253 /** 254 * Asynchronous version of g_subprocess_communicate(). Complete 255 * invocation with g_subprocess_communicate_finish(). 256 * 257 * Params: 258 * stdinBuf = Input data, or %NULL 259 * cancellable = Cancellable 260 * callback = Callback 261 * userData = User data 262 */ 263 public void communicateAsync(Bytes stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 264 { 265 g_subprocess_communicate_async(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 266 } 267 268 /** 269 * Complete an invocation of g_subprocess_communicate_async(). 270 * 271 * Params: 272 * result = Result 273 * stdoutBuf = Return location for stdout data 274 * stderrBuf = Return location for stderr data 275 * 276 * Throws: GException on failure. 277 */ 278 public bool communicateFinish(AsyncResultIF result, out Bytes stdoutBuf, out Bytes stderrBuf) 279 { 280 GBytes* outstdoutBuf = null; 281 GBytes* outstderrBuf = null; 282 GError* err = null; 283 284 auto __p = g_subprocess_communicate_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 285 286 if (err !is null) 287 { 288 throw new GException( new ErrorG(err) ); 289 } 290 291 stdoutBuf = new Bytes(outstdoutBuf); 292 stderrBuf = new Bytes(outstderrBuf); 293 294 return __p; 295 } 296 297 /** 298 * Like g_subprocess_communicate(), but validates the output of the 299 * process as UTF-8, and returns it as a regular NUL terminated string. 300 * 301 * On error, @stdout_buf and @stderr_buf will be set to undefined values and 302 * should not be used. 303 * 304 * Params: 305 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 306 * cancellable = a #GCancellable 307 * stdoutBuf = data read from the subprocess stdout 308 * stderrBuf = data read from the subprocess stderr 309 * 310 * Throws: GException on failure. 311 */ 312 public bool communicateUtf8(string stdinBuf, Cancellable cancellable, out string stdoutBuf, out string stderrBuf) 313 { 314 char* outstdoutBuf = null; 315 char* outstderrBuf = null; 316 GError* err = null; 317 318 auto __p = g_subprocess_communicate_utf8(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 319 320 if (err !is null) 321 { 322 throw new GException( new ErrorG(err) ); 323 } 324 325 stdoutBuf = Str.toString(outstdoutBuf); 326 stderrBuf = Str.toString(outstderrBuf); 327 328 return __p; 329 } 330 331 /** 332 * Asynchronous version of g_subprocess_communicate_utf8(). Complete 333 * invocation with g_subprocess_communicate_utf8_finish(). 334 * 335 * Params: 336 * stdinBuf = Input data, or %NULL 337 * cancellable = Cancellable 338 * callback = Callback 339 * userData = User data 340 */ 341 public void communicateUtf8Async(string stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 342 { 343 g_subprocess_communicate_utf8_async(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 344 } 345 346 /** 347 * Complete an invocation of g_subprocess_communicate_utf8_async(). 348 * 349 * Params: 350 * result = Result 351 * stdoutBuf = Return location for stdout data 352 * stderrBuf = Return location for stderr data 353 * 354 * Throws: GException on failure. 355 */ 356 public bool communicateUtf8Finish(AsyncResultIF result, out string stdoutBuf, out string stderrBuf) 357 { 358 char* outstdoutBuf = null; 359 char* outstderrBuf = null; 360 GError* err = null; 361 362 auto __p = g_subprocess_communicate_utf8_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 363 364 if (err !is null) 365 { 366 throw new GException( new ErrorG(err) ); 367 } 368 369 stdoutBuf = Str.toString(outstdoutBuf); 370 stderrBuf = Str.toString(outstderrBuf); 371 372 return __p; 373 } 374 375 /** 376 * Use an operating-system specific method to attempt an immediate, 377 * forceful termination of the process. There is no mechanism to 378 * determine whether or not the request itself was successful; 379 * however, you can use g_subprocess_wait() to monitor the status of 380 * the process after calling this function. 381 * 382 * On Unix, this function sends %SIGKILL. 383 * 384 * Since: 2.40 385 */ 386 public void forceExit() 387 { 388 g_subprocess_force_exit(gSubprocess); 389 } 390 391 /** 392 * Check the exit status of the subprocess, given that it exited 393 * normally. This is the value passed to the exit() system call or the 394 * return value from main. 395 * 396 * This is equivalent to the system WEXITSTATUS macro. 397 * 398 * It is an error to call this function before g_subprocess_wait() and 399 * unless g_subprocess_get_if_exited() returned %TRUE. 400 * 401 * Returns: the exit status 402 * 403 * Since: 2.40 404 */ 405 public int getExitStatus() 406 { 407 return g_subprocess_get_exit_status(gSubprocess); 408 } 409 410 /** 411 * On UNIX, returns the process ID as a decimal string. 412 * On Windows, returns the result of GetProcessId() also as a string. 413 * If the subprocess has terminated, this will return %NULL. 414 * 415 * Returns: the subprocess identifier, or %NULL if the subprocess 416 * has terminated 417 * 418 * Since: 2.40 419 */ 420 public string getIdentifier() 421 { 422 return Str.toString(g_subprocess_get_identifier(gSubprocess)); 423 } 424 425 /** 426 * Check if the given subprocess exited normally (ie: by way of exit() 427 * or return from main()). 428 * 429 * This is equivalent to the system WIFEXITED macro. 430 * 431 * It is an error to call this function before g_subprocess_wait() has 432 * returned. 433 * 434 * Returns: %TRUE if the case of a normal exit 435 * 436 * Since: 2.40 437 */ 438 public bool getIfExited() 439 { 440 return g_subprocess_get_if_exited(gSubprocess) != 0; 441 } 442 443 /** 444 * Check if the given subprocess terminated in response to a signal. 445 * 446 * This is equivalent to the system WIFSIGNALED macro. 447 * 448 * It is an error to call this function before g_subprocess_wait() has 449 * returned. 450 * 451 * Returns: %TRUE if the case of termination due to a signal 452 * 453 * Since: 2.40 454 */ 455 public bool getIfSignaled() 456 { 457 return g_subprocess_get_if_signaled(gSubprocess) != 0; 458 } 459 460 /** 461 * Gets the raw status code of the process, as from waitpid(). 462 * 463 * This value has no particular meaning, but it can be used with the 464 * macros defined by the system headers such as WIFEXITED. It can also 465 * be used with g_spawn_check_wait_status(). 466 * 467 * It is more likely that you want to use g_subprocess_get_if_exited() 468 * followed by g_subprocess_get_exit_status(). 469 * 470 * It is an error to call this function before g_subprocess_wait() has 471 * returned. 472 * 473 * Returns: the (meaningless) waitpid() exit status from the kernel 474 * 475 * Since: 2.40 476 */ 477 public int getStatus() 478 { 479 return g_subprocess_get_status(gSubprocess); 480 } 481 482 /** 483 * Gets the #GInputStream from which to read the stderr output of 484 * @subprocess. 485 * 486 * The process must have been created with %G_SUBPROCESS_FLAGS_STDERR_PIPE, 487 * otherwise %NULL will be returned. 488 * 489 * Returns: the stderr pipe 490 * 491 * Since: 2.40 492 */ 493 public InputStream getStderrPipe() 494 { 495 auto __p = g_subprocess_get_stderr_pipe(gSubprocess); 496 497 if(__p is null) 498 { 499 return null; 500 } 501 502 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) __p); 503 } 504 505 /** 506 * Gets the #GOutputStream that you can write to in order to give data 507 * to the stdin of @subprocess. 508 * 509 * The process must have been created with %G_SUBPROCESS_FLAGS_STDIN_PIPE and 510 * not %G_SUBPROCESS_FLAGS_STDIN_INHERIT, otherwise %NULL will be returned. 511 * 512 * Returns: the stdout pipe 513 * 514 * Since: 2.40 515 */ 516 public OutputStream getStdinPipe() 517 { 518 auto __p = g_subprocess_get_stdin_pipe(gSubprocess); 519 520 if(__p is null) 521 { 522 return null; 523 } 524 525 return ObjectG.getDObject!(OutputStream)(cast(GOutputStream*) __p); 526 } 527 528 /** 529 * Gets the #GInputStream from which to read the stdout output of 530 * @subprocess. 531 * 532 * The process must have been created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 533 * otherwise %NULL will be returned. 534 * 535 * Returns: the stdout pipe 536 * 537 * Since: 2.40 538 */ 539 public InputStream getStdoutPipe() 540 { 541 auto __p = g_subprocess_get_stdout_pipe(gSubprocess); 542 543 if(__p is null) 544 { 545 return null; 546 } 547 548 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) __p); 549 } 550 551 /** 552 * Checks if the process was "successful". A process is considered 553 * successful if it exited cleanly with an exit status of 0, either by 554 * way of the exit() system call or return from main(). 555 * 556 * It is an error to call this function before g_subprocess_wait() has 557 * returned. 558 * 559 * Returns: %TRUE if the process exited cleanly with a exit status of 0 560 * 561 * Since: 2.40 562 */ 563 public bool getSuccessful() 564 { 565 return g_subprocess_get_successful(gSubprocess) != 0; 566 } 567 568 /** 569 * Get the signal number that caused the subprocess to terminate, given 570 * that it terminated due to a signal. 571 * 572 * This is equivalent to the system WTERMSIG macro. 573 * 574 * It is an error to call this function before g_subprocess_wait() and 575 * unless g_subprocess_get_if_signaled() returned %TRUE. 576 * 577 * Returns: the signal causing termination 578 * 579 * Since: 2.40 580 */ 581 public int getTermSig() 582 { 583 return g_subprocess_get_term_sig(gSubprocess); 584 } 585 586 /** 587 * Sends the UNIX signal @signal_num to the subprocess, if it is still 588 * running. 589 * 590 * This API is race-free. If the subprocess has terminated, it will not 591 * be signalled. 592 * 593 * This API is not available on Windows. 594 * 595 * Params: 596 * signalNum = the signal number to send 597 * 598 * Since: 2.40 599 */ 600 public void sendSignal(int signalNum) 601 { 602 g_subprocess_send_signal(gSubprocess, signalNum); 603 } 604 605 /** 606 * Synchronously wait for the subprocess to terminate. 607 * 608 * After the process terminates you can query its exit status with 609 * functions such as g_subprocess_get_if_exited() and 610 * g_subprocess_get_exit_status(). 611 * 612 * This function does not fail in the case of the subprocess having 613 * abnormal termination. See g_subprocess_wait_check() for that. 614 * 615 * Cancelling @cancellable doesn't kill the subprocess. Call 616 * g_subprocess_force_exit() if it is desirable. 617 * 618 * Params: 619 * cancellable = a #GCancellable 620 * 621 * Returns: %TRUE on success, %FALSE if @cancellable was cancelled 622 * 623 * Since: 2.40 624 * 625 * Throws: GException on failure. 626 */ 627 public bool wait(Cancellable cancellable) 628 { 629 GError* err = null; 630 631 auto __p = g_subprocess_wait(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 632 633 if (err !is null) 634 { 635 throw new GException( new ErrorG(err) ); 636 } 637 638 return __p; 639 } 640 641 /** 642 * Wait for the subprocess to terminate. 643 * 644 * This is the asynchronous version of g_subprocess_wait(). 645 * 646 * Params: 647 * cancellable = a #GCancellable, or %NULL 648 * callback = a #GAsyncReadyCallback to call when the operation is complete 649 * userData = user_data for @callback 650 * 651 * Since: 2.40 652 */ 653 public void waitAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 654 { 655 g_subprocess_wait_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 656 } 657 658 /** 659 * Combines g_subprocess_wait() with g_spawn_check_wait_status(). 660 * 661 * Params: 662 * cancellable = a #GCancellable 663 * 664 * Returns: %TRUE on success, %FALSE if process exited abnormally, or 665 * @cancellable was cancelled 666 * 667 * Since: 2.40 668 * 669 * Throws: GException on failure. 670 */ 671 public bool waitCheck(Cancellable cancellable) 672 { 673 GError* err = null; 674 675 auto __p = g_subprocess_wait_check(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 676 677 if (err !is null) 678 { 679 throw new GException( new ErrorG(err) ); 680 } 681 682 return __p; 683 } 684 685 /** 686 * Combines g_subprocess_wait_async() with g_spawn_check_wait_status(). 687 * 688 * This is the asynchronous version of g_subprocess_wait_check(). 689 * 690 * Params: 691 * cancellable = a #GCancellable, or %NULL 692 * callback = a #GAsyncReadyCallback to call when the operation is complete 693 * userData = user_data for @callback 694 * 695 * Since: 2.40 696 */ 697 public void waitCheckAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 698 { 699 g_subprocess_wait_check_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 700 } 701 702 /** 703 * Collects the result of a previous call to 704 * g_subprocess_wait_check_async(). 705 * 706 * Params: 707 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 708 * 709 * Returns: %TRUE if successful, or %FALSE with @error set 710 * 711 * Since: 2.40 712 * 713 * Throws: GException on failure. 714 */ 715 public bool waitCheckFinish(AsyncResultIF result) 716 { 717 GError* err = null; 718 719 auto __p = g_subprocess_wait_check_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 720 721 if (err !is null) 722 { 723 throw new GException( new ErrorG(err) ); 724 } 725 726 return __p; 727 } 728 729 /** 730 * Collects the result of a previous call to 731 * g_subprocess_wait_async(). 732 * 733 * Params: 734 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 735 * 736 * Returns: %TRUE if successful, or %FALSE with @error set 737 * 738 * Since: 2.40 739 * 740 * Throws: GException on failure. 741 */ 742 public bool waitFinish(AsyncResultIF result) 743 { 744 GError* err = null; 745 746 auto __p = g_subprocess_wait_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 747 748 if (err !is null) 749 { 750 throw new GException( new ErrorG(err) ); 751 } 752 753 return __p; 754 } 755 }